home *** CD-ROM | disk | FTP | other *** search
- /* PrepMemoryUtilities.c */
- /*
- * PrepMemoryUtilities.c
- * Copyright © 1994-95 Apple Computer Inc. All rights reserved.
- */
- /* .___________________________________________________________________________________.
- | These routines simplify the computations needed for PrepareMemoryForIO. They |
- | are not specific to the framework driver. |
- | |
- | CheckpointIOTable Call CheckpointIO for the specified IOPreparationTable |
- | CompareAndSwap is used to ensure that CheckpointIO |
- | is called once only -- this is probably overkill |
- | CheckForContiguousPhysicalMapping Scan a physical mapping table to ensure |
- | that the entire area is physically contiguous. Since |
- | the driver can call MemAllocatePhysicallyContiguous, |
- | this isn't really needed anymore. |
- | NextPageIsContiguous Return TRUE if the page following the indexed page |
- | is physically contiguous to the argument page. This is |
- | used to build the longest-possible DMA request. |
- | GetMapEntryCount Given a logical address and area length, return the |
- | number of physical map entries that will be needed. |
- | NextPageBaseAddress Return the base of the physical page following the |
- | argument physical address. This is needed to determine |
- | contiguous physical mappings. It could be a macro. |
- | PageBaseAddress Return the base of the physical page containing this |
- | address (which may be a logical or physical address). |
- | This could be a macro. |
- | ClearMemory A general subroutine to clear a block of memory. It |
- | tries to be efficient. |
- .___________________________________________________________________________________.
- */
- #include "NCRDriverPrivate.h"
-
- /*
- * This is a slightly safer version of CheckpointIO that will invalidate the
- * preparationID after it completes, and will not call CheckpointIO if the
- * preparationID is already invalid.
- */
- void
- CheckpointIOTable(
- IOPreparationTable *ioTable
-
- )
- {
- OSStatus osStatus;
- IOPreparationID preparationID;
-
- Trace(CheckpointIOTable);
- while ((preparationID = ioTable->preparationID) != kInvalidID) {
- if (CompareAndSwap(
- (UInt32) preparationID, kInvalidID, (UInt32 *) &ioTable->preparationID)) {
- osStatus = CheckpointIO(preparationID, kNilOptions);
- CheckStatus(osStatus, "\pCheckpointIO");
- break;
- } /* If CompareAndSwap succeeds */
- } /* Concurrent access loop */
- }
-
-
- /*
- * This looks at the physical mapping table to ensure that the physical area
- * is contiguous. The script and per-request tables must be contiguous and the driver
- * will fail to initialize if this is not the case.
- */
- OSErr
- CheckForContiguousPhysicalMapping(
- const IOPreparationTable *ioTable
- )
- {
- ItemCount i;
- OSErr status;
-
- //** Trace(CheckForContiguousPhysicalMapping);
- status = noErr;
- for (i = 0; i < ioTable->mappingEntryCount - 1; i++) {
- if (NextPageIsContiguous(ioTable, i) == FALSE) {
- status = paramErr;
- break;
- }
- }
- CheckStatus(status, "\pNon-contiguous physical mapping");
- return (status);
- }
-
- /*
- * Return TRUE if the page following page[i] is physically contiguous with page[i].
- */
- Boolean
- NextPageIsContiguous(
- const IOPreparationTable *ioTable,
- ItemCount i
- )
- {
- //** Trace(NextPageIsContiguous);
- return (
- NextPageBaseAddress(ioTable->physicalMapping[i])
- == ioTable->physicalMapping[i + 1]
- );
- }
-
- /*
- * Return the number of mapping tables that this area will require. There is one entry
- * per page. Thus the result is the number of distinct pages in the area. areaLength
- * should not be zero.
- */
- ItemCount
- GetMapEntryCount(
- void *areaBaseAddress,
- ByteCount areaLength
- )
- {
- ItemCount result;
- ByteCount normalizedLength;
- UInt32 areaAddress;
-
- //** Trace(GetMapEntryCount);
- areaAddress = (UInt32) areaBaseAddress;
- normalizedLength = PageBaseAddress(areaAddress + areaLength - 1)
- - PageBaseAddress(areaAddress);
- result = (ItemCount) (normalizedLength / GLOBAL.pageSize) + 1;
- #if 0 && USE_LOG_LIBRARY
- WriteLogEntry(GLOBAL.logRecordPtr, 'GMap',
- LogFormat5(kLogFormatAddress, kLogFormatUnsigned,
- kLogFormatUnsigned, kLogFormatUnsigned, kLogFormatString),
- (UInt32) areaBaseAddress,
- (UInt32) areaLength,
- (UInt32) normalizedLength,
- (UInt32) result,
- "\pGetMapAreaCount"
- );
- #endif
- return (result);
- }
-
- /*
- * Return the base of the page that follows this page. This is needed to determine
- * whether a logical address range is stored in a contiguous physical address
- * range. This is essential for the script and script data area. Since our somewhat
- * limited SCSI sample does not support scatter-gather, we check it for the SCSI
- * commands, too.
- */
- PhysicalAddress
- NextPageBaseAddress(
- PhysicalAddress theAddress
- )
- {
- UInt32 result;
-
- //** Trace(NextPageBaseAddress);
- result = PageBaseAddress((UInt32) theAddress + GLOBAL.pageSize);
- return ((PhysicalAddress) result);
- }
-
- /*
- * Return the base of the page that contains the argument. The call to
- * GetLogicalPageSize should be made at driver initialization and the mask stored in
- * the driver global area.
- */
- UInt32
- PageBaseAddress(
- UInt32 theAddress
- )
- {
- UInt32 result;
-
- //** Trace(PageBaseAddress);
- result = (theAddress & ~(GLOBAL.pageMask));
- return (result);
- }
-
- /*
- * Clear a block of memory. This is optimized to use longword access whenever possible.
- */
- void
- ClearMemory(
- void *areaAddress,
- register Size byteCount
- )
- {
- register UInt8 *bytePtr;
- #define kWordSize (sizeof (UInt32))
- #define kWordMask (kWordSize - 1)
-
- //** Trace(ClearMemory);
- bytePtr = (UInt8 *) areaAddress;
- while ((((UInt32) bytePtr) & kWordMask) != 0 && byteCount > 0) {
- *bytePtr++ = 0;
- --byteCount;
- }
- while (byteCount >= kWordSize) {
- *((UInt32 *) bytePtr) = 0;
- bytePtr += kWordSize;
- byteCount -= kWordSize;
- }
- while (byteCount > 0) {
- *bytePtr++ = 0;
- --byteCount;
- }
- #undef kWordSize
- #undef kWordMax
- }
-
-